package com.se.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit;

@Slf4j
public class NettyClient {
    /**
     * @author hdu_huang
     * @date 2018/5/6
     * @desc Netty Client 启动器
     */

    private final static String address = "localhost";
    private final static int port = 9999;
    private static ClientHandler clientHandler = new ClientHandler();

    public static void start() {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group);

            bootstrap.channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            // 最后一个 Outbound 放在Inbound 前面，Inbound顺序执行，Outbound 逆序执行
                            socketChannel.pipeline().
                                    addLast(new StringDecoder(CharsetUtil.UTF_8)).
                                    addLast(new StringEncoder(CharsetUtil.UTF_8)).
                                    addLast("ping", new IdleStateHandler(30, 0, 0, TimeUnit.SECONDS)).
                                    addLast(clientHandler);//  // 自定义 ChannelHandler
                        }
                    });

            bootstrap.bind(9900); //fixme  bind和connect创建2次channel
            // Start the client.
            ChannelFuture future = bootstrap.connect(address, port).sync();
            log.info("NettyClient start success!");

            Channel channel = future.channel();
//            channel.writeAndFlush("");

            //控制台输入
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

            while (true){
                String line = in.readLine();
                if (line.equals("exit")) {
                    break;
                }
                //向服务端发送数据
                channel.writeAndFlush(line);
            }

            future.channel().closeFuture().sync();
            log.info("NettyClient end !!!");

        } catch (Exception e) {

        } finally {
            group.shutdownGracefully();
        }

    }

    public static void main(String[] args) throws Exception {
        Runnable task = NettyClient::start;

        for (int i = 0; i < 1; i++) {
            new Thread(task).start();
        }
    }
}
